import { createWalletClient, http, parseAbi, encodeFunctionData, createPublicClient, getContract } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { base } from 'viem/chains';
import { baseUniswapv3SwapRouterAbi } from '../src/abis/base.uniswapv3.swaprouter.abi'
import { baseUniswapv3PositionManagerAbi } from '../src/abis/base.uniswapv3.positionmanager.abi'
import { baseUniswapv3PoolAbi } from '../src/abis/base.uniswapv3.pool.abi'

// 1. 设置你的账户和客户端
const account = privateKeyToAccount('0x50854e1c89c49d658ac397783a22f10311009b1325b83cfab16c715e72f786f0');
const client = createWalletClient({
  account,
  chain: base,
  transport: http('https://base.llamarpc.com'),
});

const publicClient = createPublicClient({
  chain: base,
  transport: http('https://base.llamarpc.com'),
});

// 2. 定义合约地址和 ABI
const SWAP_ROUTER_ADDRESS = '0x2626664c2603336E57B271c5C0b26F421741e481';

const UNISWAPV3POOL_ADDESS = '0xd0b53D9277642d899DF5C87A3966A349A798F224';

const WALLET_ADDRESS = '0x766dcd99E834481d8647b3E7b6768C8D91C9831C';

const TOKEN_IN = '0x4200000000000000000000000000000000000006';  
const TOKEN_OUT = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';

async function approveERC20(
  tokenAddress: `0x${string}`,   // ERC20 合约地址
  spender: `0x${string}`,       // 被授权地址（例如 Uniswap SwapRouter）
  amount: bigint                // 授权金额（建议用 BigInt）
) {
  const erc20Abi = parseAbi([
    'function approve(address spender, uint256 amount) external returns (bool)',
  ]);

  const data = encodeFunctionData({
    abi: erc20Abi,
    functionName: 'approve',
    args: [spender, amount],
  });

  const txHash = await client.sendTransaction({
    to: tokenAddress,
    data,
    account,
  });

  console.log(`✅ 授权交易已发送，交易哈希: ${txHash}`);
  return txHash;
}

async function swap() {
  await approveERC20(TOKEN_IN, SWAP_ROUTER_ADDRESS, 1000000000000000n)
  await new Promise(resolve => setTimeout(resolve, 5000));
  const amountIn = 100000000000000n; 
  const feeTier = 500; 
  const amountOutMin = 0n; 
  const sqrtPriceLimitX96 = 0n; 

  const calldata = encodeFunctionData({
    abi: baseUniswapv3SwapRouterAbi,
    functionName: 'exactInputSingle',
    args: [{
      tokenIn: TOKEN_IN,
      tokenOut: TOKEN_OUT,
      fee: feeTier,
      recipient: account.address,
      amountIn,
      amountOutMinimum: amountOutMin,
      sqrtPriceLimitX96
    }],
  });

  const tx = await client.sendTransaction({
    to: SWAP_ROUTER_ADDRESS,
    data: calldata,
    account,
  });
  console.log('交易已发送：', tx);
}

async function addLiquidity({
  token0,
  token1,
  fee,
  tickLower,
  tickUpper,
  amount0Desired,
  amount1Desired,
  amount0Min,
  amount1Min,
}: {
  token0: `0x${string}`,
  token1: `0x${string}`,
  fee: number,
  tickLower: number,
  tickUpper: number,
  amount0Desired: bigint,
  amount1Desired: bigint,
  amount0Min: bigint,
  amount1Min: bigint,
}) {
  const calldata = encodeFunctionData({
    abi: baseUniswapv3PositionManagerAbi,
    functionName: 'mint',
    args: [{
      token0,
      token1,
      fee,
      tickLower,
      tickUpper,
      amount0Desired,
      amount1Desired,
      amount0Min,
      amount1Min,
      recipient: account.address,
      deadline: BigInt(Math.floor(Date.now() / 1000) + 600),
    }]
  });

  const tx = await client.sendTransaction({
    to: '0x03a520b32C04BF3bEEf7BEb72E919cf822Ed34f1',
    data: calldata,
    account,
  });

  console.log('添加流动性交易已发送:', tx);
}

async function removeLiquidityAndBurn({
  tokenId,
  amount0Min,
  amount1Min,
}: {
  tokenId: bigint,
  amount0Min: bigint,
  amount1Min: bigint
}) {
  const positionManager = getContract({
    address: '0x03a520b32C04BF3bEEf7BEb72E919cf822Ed34f1',
    abi: baseUniswapv3PositionManagerAbi,
    client: publicClient,
  });

  // Step 0: 获取当前头寸
  const position = await positionManager.read.positions([tokenId]);
  const liquidity = position[7] as bigint;
  const token0 = position[2] as `0x${string}`;
  const token1 = position[3] as `0x${string}`;

  // Step 1: decreaseLiquidity
  if (liquidity > 0n) {
    const decreaseCalldata = encodeFunctionData({
      abi: baseUniswapv3PositionManagerAbi,
      functionName: 'decreaseLiquidity',
      args: [{
        tokenId,
        liquidity,
        amount0Min,
        amount1Min,
        deadline: BigInt(Math.floor(Date.now() / 1000) + 600),
      }],
    });

    const tx1 = await client.sendTransaction({
      to: positionManager.address,
      data: decreaseCalldata,
      account,
    });

    console.log('✅ 移除流动性交易已发送:', tx1);
    await new Promise(resolve => setTimeout(resolve, 5000));
  } else {
    console.log('ℹ️ 当前流动性为 0，跳过 decreaseLiquidity');
  }

  // Step 2: collect
  const collectCalldata = encodeFunctionData({
    abi: baseUniswapv3PositionManagerAbi,
    functionName: 'collect',
    args: [{
      tokenId,
      recipient: account.address,
      amount0Max: BigInt('0xffffffffffffffffffffffffffffffff'),
      amount1Max: BigInt('0xffffffffffffffffffffffffffffffff'),
    }],
  });

  const tx2 = await client.sendTransaction({
    to: positionManager.address,
    data: collectCalldata,
    account,
  });

  console.log('✅ 收益领取交易已发送:', tx2);
  await new Promise(resolve => setTimeout(resolve, 5000));

  // ✅ Step 2.5: sweepToken (可选但推荐)
  for (const token of [token0, token1]) {
    const sweepCalldata = encodeFunctionData({
      abi: baseUniswapv3PositionManagerAbi,
      functionName: 'sweepToken',
      args: [
        token,
        0n, // amount minimum
        account.address,
      ],
    });

    try {
      const sweepTx = await client.sendTransaction({
        to: positionManager.address,
        data: sweepCalldata,
        account,
      });
      console.log(`✅ sweepToken(${token}) 成功:`, sweepTx);
      await new Promise(resolve => setTimeout(resolve, 3000));
    } catch (err) {
      console.warn(`⚠️ sweepToken(${token}) 失败，可能无剩余:`, (err as Error).message);
    }
  }

  // Step 3: burn NFT
  const burnCalldata = encodeFunctionData({
    abi: baseUniswapv3PositionManagerAbi,
    functionName: 'burn',
    args: [tokenId],
  });

  const tx3 = await client.sendTransaction({
    to: positionManager.address,
    data: burnCalldata,
    account,
  });

  console.log('🔥 NFT 已销毁，交易哈希:', tx3);
}


async function testAddLiquidity() {
  const poolContract = getContract({
    address: UNISWAPV3POOL_ADDESS,
    abi: baseUniswapv3PoolAbi,
    client: publicClient,
  });

  const [sqrtPriceX96, tick, observationIndex, observationCardinality, observationCardinalityNext, feeProtocol, unlocked] = await poolContract.read.slot0();
  const [token0, token1, fee] = await Promise.all([
    poolContract.read.token0(),
    poolContract.read.token1(),
    poolContract.read.fee(),
  ]);
  const tickSpacing = 60;

  const tickLower = Math.floor(tick / tickSpacing - 5) * tickSpacing;
  const tickUpper = Math.floor(tick / tickSpacing + 5) * tickSpacing;

  // 💰 提供小额流动性用于测试（单位视为 18 位 token）
  const amount0Desired = 100000000000000n; // 0.0001
  const amount1Desired = 100000n;

  await approveERC20(token0 as `0x${string}`, '0x03a520b32C04BF3bEEf7BEb72E919cf822Ed34f1', amount0Desired);
  await approveERC20(token1 as `0x${string}`, '0x03a520b32C04BF3bEEf7BEb72E919cf822Ed34f1', amount1Desired);

  await new Promise(resolve => setTimeout(resolve, 5000));

  await addLiquidity({
    token0: token0 as `0x${string}`,
    token1: token1 as `0x${string}`,
    fee: fee as number,
    tickLower,
    tickUpper,
    amount0Desired,
    amount1Desired,
    amount0Min: 0n,
    amount1Min: 0n,
  });
}

async function testRemoveLiquidity() {
  const tokenId = 3589825n; // 你的 NFT 头寸 ID（必须是 bigint 类型）

  await removeLiquidityAndBurn({
    tokenId,
    amount0Min: 0n,
    amount1Min: 0n,
  });
}


testRemoveLiquidity()


